home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 October
/
EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso
/
Aminet
/
mus
/
play
/
tracker_4_31.lzh
/
tracker
/
notes.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-01
|
4KB
|
177 lines
/* notes.c
vi:ts=3 sw=3:
*/
/* $Id: notes.c,v 4.13 1995/03/01 15:24:51 espie Exp espie $
* $Log: notes.c,v $
* Revision 4.13 1995/03/01 15:24:51 espie
* *** empty log message ***
*
* Revision 4.12 1995/02/21 21:13:16 espie
* Cleaned up source. Moved minor pieces of code around.
*
* Revision 4.11 1995/02/21 17:54:32 espie
* Internal problem: buggy RCS. Fixed logs.
*
* Revision 4.9 1995/02/20 22:28:50 espie
* bug in nearest_note.
*
* Revision 4.8 1995/02/20 16:49:58 espie
* Added nearest_note: round pitch to nearest entire note.
*
* Revision 4.5 1995/02/01 16:39:04 espie
* Moved includes to defs.h
*
* Revision 4.0 1994/01/11 17:50:04 espie
* Makes use of autoinit. Uses less memory, starts up faster.
* auto_init'd create_notes_table(),
* suppressed note_name static table,
* use name_of_note() instead (about 120 * 8 bytes gain).
* Amiga support.
* Added finetune.
*/
#include "defs.h"
#include <ctype.h>
#include <assert.h>
#include <math.h>
#include "song.h"
#include "channel.h"
#include "extern.h"
ID("$Id: notes.c,v 4.13 1995/03/01 15:24:51 espie Exp espie $")
/* we can put it autoinit since find_note is ALWAYS called
* prior to using pitch_table !
*/
LOCAL void create_notes_table P((void));
LOCAL void (*INIT)P((void)) = create_notes_table;
/* the musical notes correspond to some specific pitch.
* It's useful to be able to find them back, at least for
* arpeggii.
*/
short pitch_table[NUMBER_NOTES][NUMBER_FINETUNES];
LOCAL char *note_template = "C-C#D-D#E-F-F#G-G#A-A#B-";
/* note = find_note(pitch):
* find note corresponding to the stated pitch
*/
int find_note(pitch)
int pitch;
{
int a, b, i;
INIT_ONCE;
if (pitch == 0)
return -1;
a = 0;
b = NUMBER_NOTES-1;
while(b-a > 1)
{
i = (a+b)/2;
if (pitch_table[i][0] == pitch)
return i;
if (pitch_table[i][0] > pitch)
a = i;
else
b = i;
}
if (pitch_table[a][0] - FUZZ <= pitch)
return a;
if (pitch_table[b][0] + FUZZ >= pitch)
return b;
return NO_NOTE;
}
/* pitch = nearest_note(pitch, finetune):
* return the pitch corresponding to the nearest note for the given
* finetune
*/
int nearest_note(pitch, finetune)
int pitch;
int finetune;
{
int a, b, i;
INIT_ONCE;
if (pitch == 0)
return -1;
a = 0;
b = NUMBER_NOTES-1;
while(b-a > 1)
{
i = (a+b)/2;
if (pitch_table[i][finetune] == pitch)
return pitch;
if (pitch_table[i][finetune] > pitch)
a = i;
else
b = i;
}
/* need some check for the actual nearest note ? */
return pitch_table[i][finetune];
}
LOCAL void create_notes_table()
{
double base, pitch;
int i, j, k;
for (j = -8; j < 8; j++)
{
k = j < 0 ? j + 16 : j;
base = AMIGA_CLOCKFREQ/440.0/4.0 / pow(2.0, j/96.0);
for (i = 0; i < NUMBER_NOTES; i++)
{
pitch = base / pow(2.0, i/12.0);
pitch_table[i][k] = floor(pitch + 0.5);
}
}
}
char *name_of_note(i)
int i;
{
static char name[4];
if (i == NO_NOTE)
return " ";
else
{
name[0] = note_template[(i+9)%12 * 2];
name[1] = note_template[(i+9)%12 * 2 +1];
name[2] = '0' + (i-3)/12;
name[3] = 0;
return name;
}
}
int transpose_song(s, transpose)
struct song *s;
int transpose;
{
int oldt;
int i, j, n;
if (!s)
return 0;
oldt = s->info.transpose;
for (n = 0; n < s->info.maxpat; n++)
for (i = 0; i < s->info.plength; i++)
for (j = 0; j < s->ntracks; j++)
if (s->info.pblocks[n].e[j][i].note != NO_NOTE)
s->info.pblocks[n].e[j][i].note += transpose - oldt;
s->info.transpose = transpose;
return oldt;
}